<template>
  <el-dialog
    v-dialogDrag
    :visible="isVisible"
    width="30%"
    @close="handleClose"
  >
    <el-checkbox
      v-model="hasCheckedAll"
      :indeterminate="isIndeterminate"
      @change="toggleCheckAll"
    >
      全选
    </el-checkbox>
    <el-checkbox-group
      v-model="checkedItemArray"
      @change="handleChange"
    >
      <el-checkbox
        v-for="label in totalItemArray"
        :key="label"
        :label="label"
      >
        {{ label }}
      </el-checkbox>
    </el-checkbox-group>
    <div
      slot="footer"
      class="dialog-footer"
    >
      <el-button
        @click="handleClose"
      >
        取 消
      </el-button>
      <el-button
        type="primary"
        @click="handleSave"
      >
        保 存
      </el-button>
    </div>
  </el-dialog>
</template>

<script>
/**
 * # 视图管理器
 * 设置`用户数据表格`的哪些列需要显示
 */
export default {
  'name': 'ViewManager',

  'props': {
    /**
     * 设置`视图管理器`是否为显示状态
     * @type {Boolean}
     */
    'isVisible': {
      'default': false,
      'type': Boolean,
    },
    /**
     * `用户数据表格`的列的数据组成的数组
     * @type {{
     *    'label': String,
     *    'isVisible': Boolean
     *    'prop': String,
     *    'width': String,
     *  }[]}
     */
    'itemArray': {
      'default' () {
        return []
      },
      'type': Array,
    },
  },

  'data' () {
    return {
      /**
       * 已被勾选的选项组成的数组
       */
      'checkedItemArray': [],
      /**
       * 用于标记是否全选
       */
      'hasCheckedAll': true,
      /**
       * 用于标记全选框是否为不确定状态
       */
      'isIndeterminate': false,
    }
  },

  'computed': {
    /**
     * 所有选项的标签组成的数组 total
     * @return {String[]}
     */
    'totalItemArray' () {
      return this.itemArray.map(({
        label,
      }) => {
        return label
      })
    },
  },

  'created' () {
    this.setCheckedItemArray()
  },

  'methods': {
    /**
     * 处理多选框组的选项修改事件
     *
     * 用于同步全选状态和全选框确定状态
     */
    'handleChange' () {
      const checkedAmount = this.checkedItemArray.length
      const totalAmount = this.totalItemArray.length
      this.hasCheckedAll = checkedAmount === totalAmount
      this.isIndeterminate = checkedAmount > 0 && checkedAmount < totalAmount
    },
    /**
     * 处理`子系统管理器`的对话框的关闭按钮和`取消`按钮点击事件
     *
     * 关闭对话框后，还原数组到上次保存的状态
     */
    'handleClose' () {
      this.setCheckedItemArray()
      this.$emit('update:isVisible', false)
    },
    /**
     * 处理`保存`按钮的点击事件
     *
     * 保存后，按照已选择的选项将 itemArray 中的对象进行改造，并发回父组件
     */
    'handleSave' () {
      this.$emit('save', this.itemArray.map((item) => {
        item.isVisible = this.checkedItemArray.includes(item.label)
        return item
      }))
    },
    /**
     * 将 checkedItemArray 设置为 itemArray 中处于可视状态的对象组成的数组
     */
    'setCheckedItemArray' () {
      this.checkedItemArray = this.itemArray.reduce((previousArray, currentItem) => {
        if (currentItem.isVisible) {
          previousArray.push(currentItem.label)
        }
        return previousArray
      }, [])
      this.handleChange()
    },
    /**
     * 处理全选框的修改事件
     * @param {Boolean} hasBeChecked 是否选择全选框
     */
    'toggleCheckAll' (hasBeChecked) {
      this.checkedItemArray = hasBeChecked ? this.totalItemArray : []
      this.handleChange()
    },
  },
}
</script>

<style scoped lang="scss">
.dialog-footer {
  display: flex;
  justify-content: center;
}
</style>
